<template>
  <div style="height: 400px">
    <Transfer
      v-model:target-keys="targetKeys"
      class="tree-transfer"
      :data-source="dataSource"
      :list-style="{ height: '400px', width: '300px' }"
      :render="(item) => item.title"
      :show-select-all="true"
      @change="handleChange"
    >
      <template #children="{ direction, selectedKeys, onItemSelect }">
        <template v-if="direction === 'left'">
          <Tree
              v-if="treeData.length > 0"
              block-node
              checkable
              check-strictly
              default-expand-all
              :checked-keys="[...selectedKeys, ...targetKeys]"
              :tree-data="treeData"
              @check="
            (_, props) => {
              onChecked(props, [...selectedKeys, ...targetKeys], onItemSelect);
            }
          "
              @select="
            (_, props) => {
              onChecked(props, [...selectedKeys, ...targetKeys], onItemSelect);
            }
          "
          />
        </template>
      </template>
    </Transfer>
  </div>
</template>

<script lang="ts" setup>
  import { Tree, Transfer } from 'ant-design-vue';
  import { computed, ref } from 'vue';
  import { treeStruct, annoTreeData, deleteM2m, addM2ms } from '@/api/sys/anno';
  import type { TransferProps } from 'ant-design-vue';
  import { ColumnButton } from "@/api/sys/model/entitysModel";

  interface props {
    options: ColumnButton;
    data: any;
  }

  const $props = defineProps<props>();
  watch(
      () => $props.options,
      (newVal) => {
        if (newVal) {
          nextTick(() => {
            loadTree(newVal.m2mJoinButton.joinTargetClazz);
          });
        }
      },
      { immediate: true },
  );
  watch(
    () => $props.data,
    (newVal) => {
      if (newVal) {
        nextTick(() => {
          loadData($props.options.m2mJoinButton.joinTargetClazz);
        });
      }
    },
    { immediate: true },
  );

  const treeOData = ref<TransferProps['dataSource']>([]);
  const loadTree = (clazz: string) => {
    treeStruct(clazz, {}).then((res) => {
      treeOData.value = res;
      flatten(JSON.parse(JSON.stringify(treeOData.value)));
      loadData($props.options.m2mJoinButton.joinTargetClazz);
    });
  };
  const loadData = (clazz: string) => {
    annoTreeData(clazz, {
      annoM2mId: $props.options!.m2mJoinButton.id,
      joinValue: $props.data[$props.options!.m2mJoinButton.joinThisClazzField],
    }).then((res) => {
        targetKeys.value = res;
    });
  };

  const handleChange = (nextTargetKeys: string[], direction: string, moveKeys: string[]) => {
    if (direction == 'right') {
      console.log(moveKeys);
      addM2ms($props.options!.m2mJoinButton.mediumTableClazz, {
        annoM2mId: $props.options!.m2mJoinButton.id,
        targetJoinValue: moveKeys,
        thisJoinValue: $props.data[$props.options!.m2mJoinButton.joinThisClazzField],
      }).catch((res) => {
        handleChangeFail('add', moveKeys);
      });
    }
    if (direction == 'left') {
      deleteM2m($props.options!.m2mJoinButton.mediumTableClazz, {
        annoM2mId: $props.options!.m2mJoinButton.id,
        targetJoinValue: moveKeys,
        thisJoinValue: $props.data[$props.options!.m2mJoinButton.joinThisClazzField],
      }).catch((res) => {
        handleChangeFail('remove', moveKeys);
      });
    }
    console.log('targetKeys: ', nextTargetKeys);
    console.log('direction: ', direction);
    console.log('moveKeys: ', moveKeys);
    return false;
  };
  function handleChangeFail(type: 'add' | 'remove', moveKeys: string[]) {
    if (type == 'add') {
      targetKeys.value = targetKeys.value.filter((item) => {
        return !moveKeys.includes(item);
      });
    } else {
      targetKeys.value = targetKeys.value.concat(moveKeys);
    }
  }

  const transferDataSource: TransferProps['dataSource'] = [];
  function flatten(list: TransferProps['dataSource'] = []) {
    list.forEach((item) => {
      transferDataSource.push(item);
      flatten(item.children);
    });
  }

  function isChecked(selectedKeys: (string | number)[], eventKey: string | number) {
    return selectedKeys.indexOf(eventKey) !== -1;
  }

  function handleTreeData(treeNodes: TransferProps['dataSource'], targetKeys: string[] = []) {
    return treeNodes.map(({ children, ...props }) => ({
      ...props,
      disabled: targetKeys.includes(props.key as string),
      children: handleTreeData(children ?? [], targetKeys),
    }));
  }
  const targetKeys = ref<string[]>([]);

  const dataSource = ref(transferDataSource);

  const treeData = computed(() => {
    return handleTreeData(treeOData.value, targetKeys.value);
  });

  const onChecked = (e: any, checkedKeys: string[], onItemSelect: (n: any, c: boolean) => void) => {
    const { eventKey } = e.node;
    onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
  };
</script>
<style lang="less" scoped>
  :deep(.ant-transfer-list-body) {
    display: flex;
    flex: auto;
    flex-direction: column;
    overflow: scroll !important;
    font-size: 14px;
  }
</style>
